package com.zhentao.service;

import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardRequest;
import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.zhentao.config.AliyunConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * OCR身份证识别服务
 * 负责处理身份证照片识别的核心业务逻辑
 * 
 * @author zhentao
 * @version 1.0
 * @since 2025-08-27
 */
@Service
public class OcrService {
    
    private static final Logger logger = LoggerFactory.getLogger(OcrService.class);
    
    @Autowired
    private AliyunConfig aliyunConfig;
    
    /**
     * 执行身份证OCR识别
     * 
     * @param file 身份证照片文件
     * @param side 身份证面（face：正面，back：反面）
     * @return 识别结果
     * @throws Exception 识别过程中的异常
     */
    public Map<String, Object> recognizeIdcard(MultipartFile file, String side) throws Exception {
        logger.info("开始OCR识别，文件: {}, 面: {}", file.getOriginalFilename(), side);
        
        // 创建OCR客户端并执行识别
        Client client = createOcrClient();
        InputStream bodyStream = file.getInputStream();
        
        // 构建请求并调用API
        RecognizeIdcardRequest request = new RecognizeIdcardRequest().setBody(bodyStream);
        RecognizeIdcardResponse response = client.recognizeIdcardWithOptions(request, new RuntimeOptions());
        
        // 解析并返回结果
        return parseOcrResponse(response, side);
    }
    
    /**
     * 创建阿里云OCR客户端
     */
    private Client createOcrClient() throws Exception {
        String endpoint = aliyunConfig.getOcr().getEndpoint();
        String accessKeyId = aliyunConfig.getOcr().getAccessKeyId();
        String accessKeySecret = aliyunConfig.getOcr().getAccessKeySecret();
        
        logger.debug("创建OCR客户端，endpoint: {}", endpoint);
        
        // 配置凭据
        com.aliyun.credentials.Client credential;
        if (accessKeyId != null && !accessKeyId.trim().isEmpty() && 
            accessKeySecret != null && !accessKeySecret.trim().isEmpty()) {
            
            Map<String, Object> credentialConfig = new HashMap<>();
            credentialConfig.put("type", "access_key");
            credentialConfig.put("accessKeyId", accessKeyId);
            credentialConfig.put("accessKeySecret", accessKeySecret);
            
            credential = new com.aliyun.credentials.Client(
                com.aliyun.credentials.models.Config.build(credentialConfig)
            );
        } else {
            credential = new com.aliyun.credentials.Client();
        }
        
        // 创建客户端
        Config config = new Config()
                .setCredential(credential)
                .setEndpoint(endpoint)
                .setConnectTimeout(aliyunConfig.getOcr().getConnectTimeout())
                .setReadTimeout(aliyunConfig.getOcr().getReadTimeout());
        
        return new Client(config);
    }
    
    /**
     * 解析OCR响应结果
     */
    private Map<String, Object> parseOcrResponse(RecognizeIdcardResponse ocrResponse, String side) {
        if (ocrResponse == null || ocrResponse.getBody() == null) {
            throw new RuntimeException("OCR响应为空");
        }

        var responseBody = ocrResponse.getBody();
        Map<String, Object> result = new HashMap<>();

        result.put("requestId", responseBody.getRequestId());
        result.put("side", side);
        result.put("success", true);

        // 解析OCR数据并结构化返回
        if (responseBody.getData() != null) {
            Map<String, Object> extractedData = new HashMap<>();

            try {
                // 获取原始数据并记录详细日志
                Object rawData = responseBody.getData();
                String rawDataStr = rawData.toString();

                logger.info("OCR原始数据类型: {}", rawData.getClass().getName());
                logger.info("OCR原始数据内容: {}", rawDataStr);

                extractedData.put("rawData", rawDataStr);

                // 尝试解析结构化数据
                if ("face".equals(side)) {
                    // 身份证正面解析
                    Map<String, Object> faceData = parseFaceData(rawData);
                    extractedData.putAll(faceData);
                } else if ("back".equals(side)) {
                    // 身份证反面解析
                    Map<String, Object> backData = parseBackData(rawData);
                    extractedData.putAll(backData);
                }

                logger.info("OCR数据解析成功，side: {}, 提取字段: {}", side, extractedData.keySet());

            } catch (Exception e) {
                logger.error("OCR数据解析失败: {}", e.getMessage(), e);
                // 解析失败时返回基础结构
                extractedData.put("rawData", responseBody.getData().toString());
                extractedData.put("parseError", e.getMessage());

                // 根据正反面添加默认字段
                if ("face".equals(side)) {
                    extractedData.put("name", null);
                    extractedData.put("idNumber", null);
                    extractedData.put("address", null);
                } else {
                    extractedData.put("issuedBy", null);
                    extractedData.put("validPeriod", null);
                }
            }

            result.put("data", extractedData);
        }

        logger.info("OCR识别完成，requestId: {}", responseBody.getRequestId());
        return result;
    }

    /**
     * 解析身份证正面数据
     */
    private Map<String, Object> parseFaceData(Object rawData) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 将原始数据转换为字符串进行解析
            String dataStr = rawData.toString();

            // 使用正则表达式或字符串匹配提取关键信息
            // 这里需要根据阿里云OCR实际返回格式进行调整

            // 基础字段初始化
            result.put("name", null);
            result.put("idNumber", null);
            result.put("address", null);
            result.put("birth", null);
            result.put("sex", null);
            result.put("nation", null);
            result.put("rawData", dataStr);

            // 简单的字段提取逻辑（需要根据实际API响应格式调整）
            if (dataStr.contains("姓名") || dataStr.contains("name")) {
                // 提取姓名逻辑
                extractFieldFromString(result, dataStr, "name", new String[]{"姓名", "name"});
            }

            if (dataStr.contains("身份证号") || dataStr.contains("idNumber") || dataStr.contains("num")) {
                // 提取身份证号逻辑
                extractFieldFromString(result, dataStr, "idNumber", new String[]{"身份证号", "idNumber", "num"});
            }

            if (dataStr.contains("地址") || dataStr.contains("address")) {
                // 提取地址逻辑
                extractFieldFromString(result, dataStr, "address", new String[]{"地址", "address"});
            }

            logger.debug("正面数据解析结果: {}", result);

        } catch (Exception e) {
            logger.error("正面数据解析异常: {}", e.getMessage());
            result.put("parseError", e.getMessage());
        }

        return result;
    }

    /**
     * 解析身份证反面数据
     */
    private Map<String, Object> parseBackData(Object rawData) {
        Map<String, Object> result = new HashMap<>();

        try {
            String dataStr = rawData.toString();

            result.put("issuedBy", null);
            result.put("validPeriod", null);
            result.put("rawData", dataStr);

            // 提取签发机关
            extractFieldFromString(result, dataStr, "issuedBy", new String[]{"签发机关", "issuedBy", "authority"});

            // 提取有效期
            extractFieldFromString(result, dataStr, "validPeriod", new String[]{"有效期", "validPeriod", "validity"});

            logger.debug("反面数据解析结果: {}", result);

        } catch (Exception e) {
            logger.error("反面数据解析异常: {}", e.getMessage());
            result.put("parseError", e.getMessage());
        }

        return result;
    }

    /**
     * 从字符串中提取字段值
     */
    private void extractFieldFromString(Map<String, Object> result, String dataStr, String fieldName, String[] keywords) {
        // 这是一个简化的提取逻辑，实际需要根据阿里云OCR的具体返回格式进行调整
        // 这里只是提供一个框架，具体实现需要根据实际API响应进行优化

        for (String keyword : keywords) {
            if (dataStr.contains(keyword)) {
                // 简单的值提取逻辑，需要根据实际格式调整
                try {
                    // 这里需要根据实际的JSON或其他格式进行解析
                    // 暂时返回null，让前端知道字段存在但需要手动处理
                    result.put(fieldName, null);
                    break;
                } catch (Exception e) {
                    logger.warn("提取字段 {} 失败: {}", fieldName, e.getMessage());
                }
            }
        }
    }
}